﻿using System;
using System.Collections.Generic;
using AzukiMap.Map;
using AzukiMap.MapSource;
using AzukiMap.Renderer;
using AzukiMap.Tools.Logger;
using Geotools.Geometries;
using System.Windows.Media;
using System.Linq;
using System.Xml.Linq;
using AzukiMap.MapSource.Vector;
using System.Windows.Input;

namespace AzukiMap.Layer
{
    public abstract class VectorLayer : Layer, IVectorLayer
    {
        protected VectorSource _data;
        protected List<VectorLayerTheme> _layerThemes;
        protected VectorRendererSL _renderer;
        protected IVectorStyle _defaultStyle;
        protected VectorSourceTypes _vectorType;

        public VectorSource Data
        {
            get { return _data; }
        }

        public VectorSourceTypes VectorType
        {
            get { return _vectorType; }
            set { _vectorType = value; }
        }

        public int ThemeCount
        {
            get
            {
                return _layerThemes.Count;
            }
        }

        public List<string> Expressions
        {
            get
            {
                List<string> expressions = new List<string>();
                foreach (VectorLayerTheme theme in _layerThemes)
                {
                    expressions.Add(theme.Expression);
                }
                return expressions;
            }
        }

        public List<IVectorStyle> Styles
        {
            get
            {
                List<IVectorStyle> styles = new List<IVectorStyle>();
                foreach (VectorLayerTheme theme in _layerThemes)
                {
                    styles.Add(theme.Style);
                }
                return styles;
            }
        }

        public IVectorStyle DefaultStyle
        {
            get { return _defaultStyle; }
            set { _defaultStyle = value; }
        }

        public List<VectorLayerTheme> LayerThemes
        {
            get
            {
                return _layerThemes;
            }
            set
            {
                _layerThemes = value;
            }
        }


        public VectorLayer(VectorSource vectorData, MapCanvas mapCanvas, string name) 
            : base(mapCanvas, vectorData.Type, vectorData)
        {
            GTPolygon _extent = null;
            Init(vectorData, name, _extent);
        }

        public VectorLayer(VectorSource vectorData, MapCanvas mapCanvas, string name, GTPolygon maxExtent) 
            : base(mapCanvas, vectorData.Type, vectorData)
        {
            Init(vectorData, name, maxExtent);
        }

        void Init(VectorSource vectorData, string name, GTPolygon maxExtent)
        {
            _name = name;
            _maxExtent = maxExtent;
            _isRendering = false;
            _data = vectorData;
            _layerThemes = new List<VectorLayerTheme>();
            _renderer = new VectorRendererSL(MapCanvas);
            _defaultStyle = new VectorStyle();
            _vectorType = vectorData.VectorType;

            // set fill for polygons
            if (vectorData.VectorType == VectorSourceTypes.MultiPolygon ||
                vectorData.VectorType == VectorSourceTypes.Polygon)
            {
                _defaultStyle.Fill = new SolidColorBrush();
                _defaultStyle.Opacity = AzukiMapSettings.DEFAULT_FILL_OPACITY;
            }
        }

        public int AddTheme(string expression, IVectorStyle style)
        {
            VectorLayerTheme theme = new VectorLayerTheme(expression, style);
            return AddTheme(theme);
        } 

        public int AddTheme(VectorLayerTheme theme)
        {
            int themeOrder = -1;
            _layerThemes.Add(theme);
            themeOrder = _layerThemes.IndexOf(theme);
            return themeOrder;
        } 

        public void RemoveTheme(int themeOrder)
        {
            try
            {
                _layerThemes.RemoveAt(themeOrder);
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Logger.Error("Theme order number is out of range on RemoveLayerTheme().\n" + ex.StackTrace);
            }
        }

        public void RemoveAllThemes()
        {
            _layerThemes.Clear();
        }

        public void SetExpression(int themeOrder, string expression)
        {
            try
            {
                _layerThemes[themeOrder].Expression = expression;
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Logger.Error("Theme order number is out of range on SetThemeExpression().\n" + ex.StackTrace);
            }
        }

        public string GetExpression(int themeOrder)
        {
            try
            {
                return _layerThemes[themeOrder].Expression;
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Logger.Error("Theme order number is out of range on GetThemeExpression().\n" + ex.StackTrace);
                return null;
            }
        }

        public void SetStyle(int themeOrder, IVectorStyle style)
        {
            try
            {
                _layerThemes[themeOrder].Style = style;
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Logger.Error("Theme order number is out of range on SetThemeStyle().\n" + ex.StackTrace);
            }
        }

        public IVectorStyle GetStyle(int themeOrder)
        {
            try
            {
                return _layerThemes[themeOrder].Style;
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Logger.Error("Theme order number is out of range on GetThemeStyle().\n" + ex.StackTrace);
                return null;
            }
        }

        public override XElement ToXml()
        {
            return ToXml("VectorLayer");
        }

        public override XElement ToXml(string elementName)
        {
           XElement layerXml = base.ToXml(elementName);
           layerXml.Add(
               //new XElement("DefaultStyle", _defaultStyle.ToXml()),
               _defaultStyle.ToXml("DefaultStyle"),
               LayerThemesToXml(_layerThemes)
               );
           return layerXml;
        }

        public XElement LayerThemesToXml(List<VectorLayerTheme> themes)
        {
            XElement themesXml = new XElement("LayerThemes",
                from theme in themes
                //select new XElement("LayerTheme", theme.ToXml())
                select theme.ToXml()    // VectorLayerTheme
                );
            return themesXml;
        }

        public override void Parse(XElement layerXml)
        {
            base.Parse(layerXml);
            XElement defaultStyleXml = layerXml.Element("DefaultStyle");
            _defaultStyle = new VectorStyle();
            _defaultStyle.Parse(defaultStyleXml);
            ParseThemes(layerXml.Element("LayerThemes"));
        }

        public void ParseThemes(XElement layerThemesXml)
        {
            foreach (XElement themeElem in layerThemesXml.Elements("VectorLayerTheme"))
            {
                VectorLayerTheme theme = new VectorLayerTheme();
                theme.Parse(themeElem);
                AddTheme(theme);
            }
        }

    }
}
